package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"sort"
	"strconv"
	"strings"
)

type arrayFlags []string

func (i *arrayFlags) String() string {
	return "my string representation"
}

func (i *arrayFlags) Set(value string) error {
	*i = append(*i, value)
	return nil
}

type FileOffsetInfo struct {
	FileName string
	Offset   int64
}

func main() {
	var files arrayFlags
	flag.Var(&files, "f", "source data files. -f=filename,<offset>")
	dest := flag.String("d", "", "dest data files")

	args := os.Args
	fmt.Println(args)
	flag.Parse()

	var foi []FileOffsetInfo
	for _, v := range files {
		fi, err := SplitFlieString(v)
		if err == nil {
			foi = append(foi, fi)
		}
	}

	sort.Slice(foi, func(i, j int) bool {
		return foi[i].Offset < foi[j].Offset
	})

	if dest == nil {
		*dest = "dest.bin"
	}

	data := make([]byte, 0)
	num := len(foi)

	for i, v := range foi {
		fmt.Printf("File:%v, Offset:%v(%v)\n", v.FileName, v.Offset, len(data))
		buf, err := ioutil.ReadFile(v.FileName)
		if err != nil {
			fmt.Println(err.Error())
			continue
		}

		data = append(data, buf...)

		if i != num-1 {
			spaceLen := int(foi[i+1].Offset) - len(data)
			for n := 0; n < spaceLen; n++ {
				data = append(data, 0xFF)
			}
		}
	}

	ioutil.WriteFile(*dest, data, 0655)
}

func SplitFlieString(str string) (fi FileOffsetInfo, err error) {
	strs := strings.Split(str, ",")
	num := len(strs)

	fi.Offset = -1

	if num == 0 {
		return
	}

	if num < 2 {
		fi.FileName = str
		fi.Offset = 0
		return
	}

	fi.FileName = strs[0]
	base := 10
	numStr := strs[1]
	if strings.Contains(numStr, "0x") {
		base = 16
		numStr = strings.ReplaceAll(numStr, "0x", "")
	}
	fi.Offset, err = strconv.ParseInt(numStr, base, 32)
	if err != nil {
		fi.Offset = -1
	}

	return
}
